package com.weim.weim.util;

import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.InputStream;

/**
 * @author wangxiaochen
 * @date 2019/11/22
 */
@Slf4j
public class VideoUtil {
    private static int timeout = 20*1000000;

    /**
     * 获取指定视频的帧并保存为图片至指定目录
     * @param
     * @throws Exception
     */
    public static byte[] fetchFrame(InputStream inputStream) throws Exception {
        long currentTimeMillis = System.currentTimeMillis();
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(inputStream);
        ff.setOption("rw_timeout",String.valueOf(timeout));
        ff.setTimeout(timeout);
        byte[] imageInByte;
//        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
//            long start = System.currentTimeMillis();
//            File targetFile = new File(videofile);
            ff.start();
            int lenght = ff.getLengthInFrames();
            int i = 0;
            Frame f = null;
            while (i < lenght) {
                // 过滤前5帧，避免出现全黑的图片，依自己情况而定
                f = ff.grabImage();
                if(i < 5){
                    i++;
                    continue;
                }
//                if ((i > 5) && (f.image != null)) {
                    break;
//                }
//                i++;
            }
            ff.stop();
            Java2DFrameConverter converter = new Java2DFrameConverter();
            BufferedImage fecthedImage = converter.getBufferedImage(f);
            //视频旋转角度,可能是null
            String rotateOld = ff.getVideoMetadata("rotate");
            if (!StringUtils.isEmpty(rotateOld)) {
                fecthedImage = rotateImage(fecthedImage, Integer.parseInt(rotateOld));
            }
            imageInByte = ImgCompress.imgCover(fecthedImage);
        } catch (Exception e) {
            log.error("系统异常:{}", e.getMessage(), e);
            throw e;
        } finally {
            if (inputStream != null){
                inputStream.close();
            }
            if (ff != null) {
                ff.release();
                ff.close();
            }
        }
        log.info("耗时 {}",System.currentTimeMillis()-currentTimeMillis);
        return imageInByte;
    }


    public static BufferedImage rotateImage(BufferedImage bufferedimage, int degree) {
        //空的图片
        BufferedImage img =null;
        int angle = degree;
        try {// 从服务器读取照片
            int h = 0;
            int w = 0;
            if (angle != 0) {
                if (angle / 90 % 2 == 1) {// 旋转角度为90或270...时，图像的长宽对换
                    h = bufferedimage.getWidth();
                    w = bufferedimage.getHeight();
                } else {
                    w = bufferedimage.getWidth();
                    h = bufferedimage.getHeight();
                }
            } else {// 旋转角度为0时，返回
                return bufferedimage;
            }
            // 将像素值转换为颜色分量和 alpha 分量的方法,返回此 ColorModel 的转换类型。
            int type = bufferedimage.getColorModel().getTransparency();
            img = new BufferedImage(w, h, type);
            // 创建一个 Graphics2D，可以将它绘制到此 BufferedImage 中。
            Graphics2D graphics2d = img.createGraphics();
            // 将当前 Graphics2D Transform 与平移转换连接。后续呈现相对于前一位置平移指定的距离。
            graphics2d.translate((w - bufferedimage.getWidth()) / 2, (h - bufferedimage.getHeight()) / 2);
            graphics2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, // 插值提示键
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);// 插值提示值——图像中最接近整数坐标样本的 4 种颜色样本被线性地插入，以生成一个颜色样本
//            graphics2d.rotate(Math.toRadians(angle), bufferedimage.getWidth() / 2, bufferedimage.getHeight() / 2);// 注意此处是原图片的宽和长，不是计算后的，用计算后的宽和长，保存后又黑边
            /*******************0727***********************/
            graphics2d.rotate(Math.toRadians(angle), Double.valueOf(bufferedimage.getWidth() / 2), Double.valueOf(bufferedimage.getHeight() / 2));// 注意此处是原图片的宽和长，不是计算后的，用计算后的宽和长，保存后又黑边
            graphics2d.drawImage(bufferedimage, null, null);
            graphics2d.dispose();
        } catch (Exception e) {
            log.error("系统异常",e);
        }
        return img;
    }

    /**
     * 获取指定时间视频的帧并保存为图片至指定目录
     * @param multipartFile
     * @return
     * @throws Exception
     */
    public static byte[] randomGrabberFFmpegImage(MultipartFile multipartFile) throws Exception {
        long currentTimeMillis = System.currentTimeMillis();
        FFmpegFrameGrabber grabber = null;
        byte[] imageInByte;
        try {
            grabber = new FFmpegFrameGrabber(multipartFile.getInputStream());
            grabber.start();

            // 获取视频总帧数
             int lengthInVideoFrames = grabber.getLengthInVideoFrames();
            // 获取视频时长， / 1000000 将单位转换为秒
//            long delayedTime = grabber.getLengthInTime() / 1000000;

            // 跳转到视频对应时间-第一秒
//            grabber.setTimestamp(1000000L);

            // 截取图片第五帧
            int i = 0;
            Frame f = null;
            while (i < lengthInVideoFrames) {
                f = grabber.grabImage();
                if(i == 5){
                    break;
                }
                i++;
            }
            Java2DFrameConverter converter = new Java2DFrameConverter();
            BufferedImage fecthedImage = converter.getBufferedImage(f);
            //视频旋转角度,可能是null
            String rotateOld = grabber.getVideoMetadata("rotate");
            if (!StringUtils.isEmpty(rotateOld)) {
                fecthedImage = rotateImage(fecthedImage, Integer.parseInt(rotateOld));
            }
            imageInByte = ImgCompress.imgCover(fecthedImage);
        } catch (Exception e) {
            log.error("系统异常:{}", e.getMessage(), e);
            throw e;
        } finally {
            try {
                if (grabber != null) {
                    grabber.stop();
                    grabber.release();
                    //图片截取完成后需要主动回收
//                    System.gc();
                }
            } catch (FFmpegFrameGrabber.Exception e) {
                log.error("获取文件信息失败：{}", e.getMessage(),e);
            }
        }
        log.info("耗时 {}",System.currentTimeMillis()-currentTimeMillis);
        return imageInByte;
    }

}
